package com.javasea.scene.distributed.locks.redis.redissionimpl;

import com.javasea.scene.distributed.locks.redis.BeanTools;
import lombok.extern.slf4j.Slf4j;
import org.redisson.api.RLock;
import org.redisson.api.RedissonClient;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;

import java.util.concurrent.TimeUnit;

/**
 * @ClassName redissionimpl
 * @Description
 * 1. 通过redissonClient获取RLock实例
 * 2. tryLock获取尝试获取锁，第一个是等待时间，第二个是锁的超时时间，第三个是时间单位
 * 3. 执行完业务逻辑后，最终释放锁
 * @Author longxiaonan@163.com
 * @Date 2019/10/13 0013 22:21
 */
@Slf4j
@RequestMapping
@RestController
public class RedissionController {

    @Autowired
    private RedissonClient redissonClient;

    @Autowired
    private RedissonService redissonService;

    @GetMapping("/test/redission")
    public String test(){
//        for (int i = 0; i < 3; i++) {
//            redissonService.test();
//        }
        RLock distribute_lock = redissonClient.getLock("distribute_lock");
        log.info("获取到锁[{}]， 锁状态为[{}]", distribute_lock.getName(), distribute_lock.isLocked());
        if(distribute_lock.isLocked()){
            // 如果不在加锁失败进行return，那么下个请求会在tryLock等待上个请求完成后释放锁后执行
            // leaseTime后会自动释放锁，当程序执行完去finally再是否锁的时候，再是否锁会报错。
            log.info("加锁失败");
            return "加锁失败";
        }
        try {
            log.info("开始加锁");

            distribute_lock.lock();

            // 如果leaseTime设置为-1，那么默认leaseTime是30s，也就是redis的key的TTL是30s，
            // 当TTL从30s减到20s的时候又会重置为30s
//            boolean result = distribute_lock.tryLock(2, -1, TimeUnit.SECONDS);

            // 尝试加锁，最多等待100秒，上锁以后10秒自动解锁,没有 Watch dog, 不推荐这种写法！！！
//            boolean result = distribute_lock.tryLock(20, 10, TimeUnit.SECONDS);
//            if(result) {
            log.info("加锁成功");
            Thread.sleep(60_000);
//            }
            // TODO业务代码
        } catch (InterruptedException e) {
            e.printStackTrace();
        } finally {
            // 如果在leaseTime自动释放锁，那么heldByCurrentThread 为 false
            boolean heldByCurrentThread = distribute_lock.isHeldByCurrentThread();
            if (heldByCurrentThread && distribute_lock.isLocked()) {
                log.info("释放锁");
                distribute_lock.unlock();
            }
        }
        log.info("执行完成");
        return "执行完成";
    }
}
